package com.example.springdemo.design_model.prototype;

import lombok.Data;

import java.io.*;

/**
 * 原型模式
 * @author zhangding
 * @date 2022年3月23日09:17:14
 */
class Prototype implements Cloneable{
    @Override
    public Prototype clone(){
        Prototype prototype = null;
        try{
            prototype = (Prototype)super.clone();
        }catch(CloneNotSupportedException e){
            e.printStackTrace();
        }
        return prototype;
    }
}
class ConcretePrototype extends Prototype{
    int i = 666;
    public void show(){
        System.out.println(i);
        System.out.println("原型模式实现类");
    }
    public void setI(int i) {
        this.i = i;
    }
}
class ConcreteP2{
    @Override
    public ConcreteP2 clone(){
        ConcreteP2 prototype2 = null;
        try{
            prototype2 = (ConcreteP2)super.clone();
        }catch(CloneNotSupportedException e){
            e.printStackTrace();
        }
        return prototype2;
    }
}
class PrototypeTest{
    public static void main(String[] args) {
        ConcretePrototype concretePrototype = new ConcretePrototype();
        concretePrototype.setI(888);
        ConcretePrototype concretePrototype1 = (ConcretePrototype)concretePrototype.clone();
        System.out.println(concretePrototype.hashCode());
        System.out.println(concretePrototype1.hashCode());
        System.out.println(concretePrototype1.i);
        System.out.println(concretePrototype.i);
    }
}

/**
 * 深拷贝
 */
@Data
class DeepCloneTarget implements Serializable{
    private static final long serialVersionUID = 9120615610229208096L;
    private String cloneName;
    DeepCloneTarget(String cloneName){
        this.cloneName = cloneName;
    }
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
@Data
class DeepPrototype implements Serializable,Cloneable{
    public String name;
    public DeepCloneTarget deepCloneTarget = new DeepCloneTarget("9999");
    DeepPrototype(){
        super();
    }

    /**
     * 方式一：clone方法
     * @return
     * @throws CloneNotSupportedException
     */
    @Override
    public Object clone() throws CloneNotSupportedException {
        Object deep = null;
        deep = super.clone();
        DeepPrototype deepPrototype = (DeepPrototype) deep;
        deepPrototype.deepCloneTarget = (DeepCloneTarget) deepCloneTarget.clone();
        return deepPrototype;
    }

    /**
     * 方式二：序列化
     * @return
     */
    public Object deepClone() throws IOException {
        ByteArrayOutputStream bos = null;
        ObjectOutputStream oos = null;
        ByteArrayInputStream bis = null;
        ObjectInputStream ois = null;
        try {
            // 序列化
            bos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(bos);
            oos.writeObject(this);
            // 反序列化
            bis = new ByteArrayInputStream(bos.toByteArray());
            ois = new ObjectInputStream(bis);
            DeepPrototype result = (DeepPrototype) ois.readObject();
            return result;
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }finally {
            bos.close();
            oos.close();
            bis.close();
            ois.close();
        }
    }
}
class PrototypeTest2{
    public static void main(String[] args) throws CloneNotSupportedException, IOException {
        DeepPrototype deepPrototype = new DeepPrototype();
        DeepPrototype deepPrototype1 = (DeepPrototype) deepPrototype.deepClone();
        System.out.println(deepPrototype1.deepCloneTarget.getCloneName());
        deepPrototype.deepCloneTarget.setCloneName("dfshjikjhdsl");
        System.out.println(deepPrototype1.deepCloneTarget.getCloneName());
        System.out.println(deepPrototype.deepCloneTarget.getCloneName());
    }
}

